package com.framework.util;

import org.apache.commons.lang3.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.Year;
import java.time.YearMonth;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

/**
 * @Description: TODO
 * @Author: xiaoche
 * @Date: 2021/9/8 12:34
 */
public class DateUtil {
    public static Calendar getCalendar(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);

        return c;
    }

    /**
     * 获取当前日期，所有代码中必须通过此方法获取当前日期
     *
     * @return
     */
    public static Date currDate() {
        return new Date();
    }

    public static Date afterSecond2Date(Date date, long second) {
        long time = date.getTime() + second * 1000;
        return new Date(time);
    }

    public static Date parse(String source, String pattern) {
        return parse(source, new SimpleDateFormat(pattern));
    }

    public static Date parse(String source, SimpleDateFormat sdf) {
        if (StringUtils.isEmpty(source)) {
            return null;
        }
        try {
            return sdf.parse(source);
        } catch (Exception e) {
            throw new IllegalArgumentException(e.getMessage(), e);
        }
    }

    /**
     * 格式化date为 pattern格式字符串
     *
     * @param date
     * @return
     */
    public static String format(Date date, String pattern) {
        return format(date, new SimpleDateFormat(pattern));
    }

    public static String format(Date date, DateFormat df) {
        if (date == null) {
            return null;
        }
        return df.format(date);
    }

    public static Long[] getDistanceTimes(Date startTime, Date endTime) {
        Long time1 = startTime.getTime();
        Long time2 = endTime.getTime();
        Long diff;
        if (time1 < time2) {
            diff = time2 - time1;
        } else {
            diff = time1 - time2;
        }
        Long day = diff / (24 * 60 * 60 * 1000);
        Long hour = (diff / (60 * 60 * 1000) - day * 24);
        Long min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
        Long sec = (diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        Long[] times = {day, hour, min, sec};
        return times;
    }

    public static long[] getDistanceTimes(String starttime, String endtime) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date one;
        Date two;
        long day = 0;
        long hour = 0;
        long min = 0;
        long sec = 0;
        try {
            one = df.parse(starttime);
            two = df.parse(endtime);
            long time1 = one.getTime();
            long time2 = two.getTime();
            long diff;
            if (time1 < time2) {
                diff = time2 - time1;
            } else {
                diff = time1 - time2;
            }
            day = diff / (24 * 60 * 60 * 1000);
            hour = (diff / (60 * 60 * 1000) - day * 24);
            min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
            sec = (diff / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        long[] times = {day, hour, min, sec};
        return times;
    }

    public static String dealStartTime(String startTime) {
        if (StringUtils.isBlank(startTime) || !isDate(startTime)) {
            return null;
        }
        return startTime + " 00:00:00";
    }

    public static String dealEndTime(String endTime) {
        if (StringUtils.isBlank(endTime) || !isDate(endTime)) {
            return null;
        }
        return endTime + " 23:59:59";
    }

    /**
     * “YYYY-MM-DD”
     *
     * @param date
     * @return
     */
    public static boolean isDate(String date) {
        Pattern p = Pattern.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))?$");
        return p.matcher(date).matches();
    }

    public static String getMinuteAgoOrAfterString(Date date, int num) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        calendar.add(Calendar.MINUTE, num);
        return sdf.format(calendar.getTime());
    }

    public static Date getMinuteAgoOrAfter(Date date, int num) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, num);
        return calendar.getTime();
    }

    public static Calendar buildCalendar(Date date, int type, int amount) {
        Calendar calendar = getCalendar(date);
        if (type == Calendar.YEAR) {
            calendar.add(Calendar.YEAR, amount);
        }
        if (type == Calendar.MONTH) {
            calendar.add(Calendar.MONTH, amount);
        }
        if (type == Calendar.DAY_OF_YEAR) {
            calendar.add(Calendar.DAY_OF_YEAR, amount);
        }
        if (type == Calendar.HOUR) {
            calendar.add(Calendar.HOUR, amount);
        }
        if (type == Calendar.MINUTE) {
            calendar.add(Calendar.MINUTE, amount);
        }
        if (type == Calendar.SECOND) {
            calendar.add(Calendar.SECOND, amount);
        }
        return calendar;
    }
    public static List<String> getTimePeriodFromTwoTimeList(int syear, int smonth, int sdayOfMonth, int eyear, int emonth, int edayOfMonth) {
        LocalDate start = LocalDate.of(syear, smonth, sdayOfMonth);
        LocalDate end = LocalDate.of(eyear, emonth, edayOfMonth);
        long timstrap = start.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
        long endtime = end.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
        return getTimePeriodFromTwoTime(timstrap, endtime, 2);
    }


    protected static List<String> getTimePeriodFromTwoTime(Long startTime, Long endTime, Integer timeType) {
        LocalDate start = Instant.ofEpochMilli(startTime).atZone(ZoneOffset.ofHours(8)).toLocalDate();
        LocalDate end = Instant.ofEpochMilli(endTime).atZone(ZoneOffset.ofHours(8)).toLocalDate();
        List<String> result = new ArrayList<>();
        if (timeType == 0) {
            Year startyear = Year.from(start);
            Year endYear = Year.from(end);
            for (long i = 0; i <= ChronoUnit.YEARS.between(startyear, endYear); i++) {
                result.add(startyear.plusYears(i).toString());
            }
        } else if (timeType == 1) {
            YearMonth from = YearMonth.from(start);
            YearMonth to = YearMonth.from(end);
            for (long i = 0; i <= ChronoUnit.MONTHS.between(from, to); i++) {
                result.add(from.plusMonths(i).toString());
            }
        } else if (timeType == 2) {
            for (long i = 0; i <= ChronoUnit.DAYS.between(start, end); i++) {
                result.add(start.plus(i, ChronoUnit.DAYS).toString());
            }
        }
        return result;
    }
}
